#pragma once

#include "d3d9.h"
#include "d3dx9.h"
#include <vector>

// Add pragma comments so you do not have to change
// the property dependencies
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

struct s_Model
{
	// Create world matrices for class
	D3DXMATRIX	worldMat, scaleMat, rotMat, transMat;
	// X file variables
	ID3DXMesh*			m_pMesh;
	D3DMATERIAL9*		m_pMaterials;
	DWORD				m_dwNumMaterials;
	LPDIRECT3DTEXTURE9*	m_pMeshTextures;
	// Placement variables
	D3DXVECTOR3			vecPos;
	D3DXVECTOR3			vecRot;
	D3DXVECTOR3			vecSpeed;
	D3DXVECTOR3			vecScale;
	// Bool check for collision detection, if model is placed in level
	// switch to true, should be false by default
	bool				bPlaced;
	// we need to know if we are using a corner to piece to create extra bounding
	bool				bCornerPiece;
	// Set a bool so we check if the player can exit the door
	bool				bShielded;
	// AABB members
	D3DXVECTOR3			vecBBMin;
	D3DXVECTOR3			vecBBMax;
	D3DXVECTOR3			vecModelBounds[8];
	D3DXVECTOR3			worldBBmin;
	D3DXVECTOR3			worldBBmax;
	// ID that will say what type of track it is
	short				sTypeID;
	// Turn piece variable so player can fall when not visibily on the object
	D3DXVECTOR3			vecCornerBoxTrans; // holds translation piece for extra collision on corner pieces.
	short				sCornerChange; // variable to alter translation of extra bounding box on the corner pieces.
	D3DXVECTOR3			vecExtraBox;
	D3DXMATRIX			extraTransMat, extraWorldMat;
	// Extra bounding box variables
	D3DXVECTOR3			vecExtraBBMin;
	D3DXVECTOR3			vecExtraBBMax;
	D3DXVECTOR3			vecExtraModelBounds[8];
	D3DXVECTOR3			vecExtraWorldBBmin;
	D3DXVECTOR3			vecExtraWorldBBmax;
};

class ModelManager
{
private:
	// Singleton instance
	static ModelManager*	m_ModelInstance;
	// Model index to traverse through the vector
	int					iModelIndex;
	// Pointer to the D3D Device
	IDirect3DDevice9*	m_Device;
	// Mesh to show the bounding box for testing purposes
	ID3DXMesh*			m_pBBmesh;
	// Mesh to hold information for smaller bounding area of corner piece
	ID3DXMesh*			m_pExtraCollisionMesh;
	// Mesh to hold spere that will block the exit
	ID3DXMesh*			m_pShieldMesh;
	D3DMATERIAL9		m_ShieldMat;
	// Variables for running the auto path
	int					iDestination;
	D3DXVECTOR3			vecDistance;
	D3DXVECTOR3			vecMidpoint;
	float				fMaxJump;
	// Variables to keep time for the path
	// Player won't be able to stay on one
	// the tracks for too long
	LONG				lCurrentTime;
	LONG				lStartTime;

public:
	ModelManager(void);
	~ModelManager(void);

	// Create the vector to hold the models
	std::vector<s_Model*> modelList;
	bool				bPausePath;
	bool				bFirstTrack;
	bool				bJumping;
	int					iPathTimer;

	// Singleton functions
	static ModelManager* GetInstance(void);
	void DeleteInstance(void);
	// Initializing the manager
	void InitModelManager(IDirect3DDevice9* m_pD3DDevice);
	// Load models
	int LoadModel(LPCSTR xFileName, D3DXVECTOR3 vecPos, bool bPlaced);
	// Drawing models
	void DrawModel(void);
	// Return the position of the player (ALWAYS IN POSITION 0)
	D3DXVECTOR3 GetPlayerPos(void);
	// find out if corner piece so physics can call additional collision if necessary
	bool GetBCornerPiece(int iModelID);
	D3DXVECTOR3 GetModelPos(int iModelID);
	bool GetModelPlaced(int iModelID);
	// Modifying models
	void ModifyModelPos(int iModelID, float fXChange, float fYChange, float fZChange);
	void PlaceTrack(int iModelID, float fXChange, float fYChange, float fZChange, bool bPlacedin, bool bFightMode );
	void ResetPlayer(short sCheckpoint);
	void ModifyModelRot(int iModelID, float fXChange, float fYChange, float fZChange );
	void RunPath(int iLoadedModels, int iLastTrack, float fDeltaTime);
	int CheckPathTime(void);
	void SetTypeID(int iTrackID, short iTypeID);
	// check to see if shield on exit should still be in play
	void CheckShieldStatus(short sMiniGameCount);
	// Collision Detection functions
	void CalculateWorldBB(int iModelID);
	bool CollisionDetection(int iModelID);
	void CalculateExtraBB(int iModelID);
	bool CornerCollision(int iModelID); // collision check for empty space on corner piece track
	bool ShieldCollision(void); // calculate collision with the shield
	bool TrackPlacementCollision(int iCurrentTrack, int iModelID);
	// Functions for destroying models
	void DestroyModel(int iModelID);
	void DestroyAllModels(void);
};
